// Handling of objects
#include "uescript.h"

/*========================
	Init
========================*/

// Inits an object
ues_mem_t*	UES_Object_Alloc(unsigned char type) //, ues_env_t *pEnv, unsigned short usDefID)
{
	ues_mem_t *obj=UES_TagMalloc(TAG_OBJECT,sizeof(ues_mem_t));
	/*unsigned int n;
	ues_def_t *pDef;
	ues_struct_t *pStruct;*/
	obj->cast = type;
	
	// Set the default
	/*switch(type)
	{
	case UES_CAST_FUNCTION:
	case UES_CAST_STRING:
	case UES_CAST_PTR:
	case UES_CAST_INT:
		obj->size=sizeof(int);
		//obj->memptr =UES_TagMalloc(TAG_OBJECTMEM,sizeof(int));
		break;
	case UES_CAST_FLOAT:
		obj->size=sizeof(float);
		//obj->memptr = UES_TagMalloc(TAG_OBJECTMEM,sizeof(float));
		break;
	case UES_CAST_SINGLE_DEF:
		if (usDefID>MAX_UES_SINGLE_DEFS)
		{
			UES_TagFree(obj);
			return NULL;
		}
		pDef=pEnv->defs[usDefID];
		switch(pDef->ucType)
		{
		case UES_CAST_FUNCTION:
		case UES_CAST_STRING:
		case UES_CAST_PTR:
		case UES_CAST_INT:
			obj->size=sizeof(int);
			//obj->memptr=UES_TagMalloc(TAG_OBJECTMEM,sizeof(int));
			break;
		case UES_CAST_FLOAT:
			obj->size=sizeof(float);
			//obj->memptr=UES_TagMalloc(TAG_OBJECTMEM,sizeof(float));
			break;
		default:
			UES_TagFree(obj);
			return NULL;
		}
		break;
	case UES_CAST_STRUCT:
		if (usDefID>MAX_UES_STRUCTS)
		{
			UES_TagFree(obj);
			return NULL;
		}
		pStruct=&pEnv->structs[usDefID];
		obj->size=0;
		
		for (n=0; n<pStruct->pDefs.numArgs; n++)
		{

		}
	default:
		UES_TagFree(obj);
		return NULL;
	}*/
	// Zero out memory
	/*if (obj->memptr)
		memset(obj->memptr, 0, obj->size);*/
	obj->isStatic=FALSE;
	obj->isAlloced=FALSE;
	obj->isArgument=FALSE;
	return obj;
}

// Free object
void		UES_Object_Destroy(ues_mem_t *obj)
{
	switch(obj->cast)
	{
	case UES_CAST_PTR:
	case UES_CAST_STRING:
	case UES_CAST_FUNCTION:
	case UES_CAST_STRUCT:
	case UES_CAST_SINGLE_DEF:
		if (obj->memptr)
			UES_TagFree(obj->memptr);
		break;
	default:
		UES_TagFree(obj->memptr);
		break;
	}
	UES_TagFree(obj);
}

/*
	h=70/60*(310+x);
	h=95/60*x;
	70/s*(310+x)=95/s*x;
	70*(310+x)=95*x;
	310+x=95*x/70;
	21700+70x=95x;
	21700=25x;
	x=868;

	h=95/60*x;
	h=95/60*868;
	h=1374.3333...;
*/

/*=========================
	Object Functions
=========================*/

// Returns the size of a object
size_t	UES_Object_GetSize(ues_mem_t *pObj)
{
	ues_struct_t *pStruct;

	switch(pObj->cast)
	{
	case UES_CAST_FUNCTION:
	case UES_CAST_PTR:
	case UES_CAST_STRING:
	case UES_CAST_INT:
		return sizeof(int);
	case UES_CAST_FLOAT:
		return sizeof(float);
	case UES_CAST_STRUCT:
		pStruct=pObj->memptr;
		return pStruct->sSize;
	default:
		return 0;
	}
}

// Sets the data to object
void	UES_Object_SetData(ues_mem_t *obj, void *dptr, unsigned int size)
{
	switch(obj->cast)
	{
	case UES_CAST_FUNCTION:
	case UES_CAST_PTR:
	case UES_CAST_STRUCT:
	//case UES_CAST_SINGLE_DEF:
	case UES_CAST_ARRAY:
		obj->memptr=dptr;
		obj->size=size;
		break;
	case UES_CAST_STRING:
		obj->memptr=UES_TagMalloc(TAG_PROGSTRING, size);
		memcpy(obj->memptr, dptr, size);
		obj->size=size;
		break;
	case UES_CAST_INT:
		obj->memptr=dptr;
		obj->size=sizeof(int);
		break;
	case UES_CAST_FLOAT:
		obj->memptr=dptr;
		obj->size=sizeof(float);
		break;
	default:
		if (obj->size < size)
		{
			c_api->Print("Warning: Attempted buffer-overflow\n");
			size=obj->size;
		}
		memcpy(obj->memptr, dptr, size);
		break;
	}
}

// Retrive ptr to data
void*	UES_Object_GetData(ues_mem_t *obj)
{
	switch(obj->cast)
	{
	case UES_CAST_FUNCTION:
	case UES_CAST_PTR:
	case UES_CAST_STRING:
	case UES_CAST_STRUCT:
	case UES_CAST_SINGLE_DEF:
		return obj->memptr;
	default:
		return &obj->memptr;
	}
}

// Copy a object
ues_mem_t*	UES_Object_Copy(ues_mem_t *obj)
{
	ues_mem_t *pObj=UES_TagMalloc(TAG_OBJECT,sizeof(*pObj));
	ues_function_t *pFunction;
	ues_function_t *pOrigFunction;
	ues_struct_t *pStruct;
	ues_struct_t *pOrigStruct;
	unsigned int n;
	pObj->size=obj->size;
	pObj->cast=obj->cast;
	
	switch(obj->cast)
	{
	case UES_CAST_FUNCTION:
		pOrigFunction=obj->memptr;
		pFunction=UES_TagMalloc(TAG_CLASS,sizeof(*pFunction));
		pFunction->args=UES_TagMalloc(TAG_CLASS,sizeof(*pFunction->args));
		pFunction->args->numArgs=pOrigFunction->args->numArgs;
		if (pOrigFunction->retCast==UES_CAST_FUNCTION)
		{
			pFunction->retArgs=UES_TagMalloc(TAG_CLASS,sizeof(*pFunction->retArgs));
			pFunction->retArgs->numArgs=pOrigFunction->retArgs->numArgs;
			pFunction->retIsAlloced=pOrigFunction->retIsAlloced;

			for (n=0; n<pFunction->retArgs->numArgs; n++)
				pFunction->retArgs->args[n]=UES_Object_Copy(pOrigFunction->retArgs->args[n]);
		}
		pFunction->retCast=pOrigFunction->retCast;
		pFunction->type=pOrigFunction->type;
		
		for (n=0; n<pFunction->args->numArgs; n++)
			pFunction->args->args[n]=UES_Object_Copy(pOrigFunction->args->args[n]);

		pObj->memptr=pFunction;
		break;
	case UES_CAST_STRUCT:
		pOrigStruct=obj->memptr;
		pStruct=UES_TagMalloc(TAG_CLASS,sizeof(*pStruct));
		pStruct->defs.numArgs=pOrigStruct->defs.numArgs;
		pStruct->sSize=pOrigStruct->sSize;
		pStruct->iStructID=pOrigStruct->iStructID;
		
		for (n=0; n<pStruct->defs.numArgs; n++)
		{
			pStruct->defs.args[n]=UES_Object_Copy(pOrigStruct->defs.args[n]);
			pStruct->defs.names[n]=pOrigStruct->defs.names[n];
		}
		pObj->memptr=pStruct;
		break;
	case UES_CAST_SINGLE_DEF:
		break;
	default:
		pObj->memptr=obj->memptr;
		break;
	}
	pObj->isStatic=FALSE;
	pObj->isAlloced=FALSE;
	return pObj;
}